// 取货码
package coupon

import (
	"context"
	"sale-admin/config/redis"
	"sale-admin/internal/dal"
	"sale-admin/internal/dao"
	"sale-admin/internal/define"
	"sale-admin/internal/models"
	"time"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/logx"
)

// CreatePickupCode 生成取货码
// expiredAt 过期时间
// outTradeNo 订单交易号
func CreatePickupCode(ctx context.Context, expiredAt int64, outTradeNo, merchantID string) (string, error) {
	code := ""
	timeoutN := 0
	// 生成一个不重复的优惠码
	for {
		rdb := redis.NewDB()
		tempCode := genCode()
		timeoutN++
		if timeoutN >= 100 {
			return "", errorx.New("获取取货码超时", -1)
		}
		// 增加一个并发锁，用于处理接口发码和后台生成码的并发问题
		redisCtx, redisCancel := context.WithTimeout(context.Background(), time.Second*3)
		success, _ := rdb.SetNX(redisCtx, define.RedisCouponCodeGenLock+tempCode, 1, time.Second*5).Result()
		redisCancel()
		if !success {
			time.Sleep(time.Millisecond * 100)
			continue
		}
		if (dao.CouponCode{}).Exists(ctx, dal.Q, tempCode) {
			continue
		}
		code = tempCode
		break
	}
	// 生成一个主码，指定失效时间
	err := dao.CouponCode{}.Create(ctx, dal.Q, []*models.CouponCode{
		{
			BatchID:    "0",
			Code:       code,
			ExpiredAt:  expiredAt,
			MerchantID: merchantID,
			Status:     int(define.CouponCodeStatus_UnUsed),
		},
	})
	if err != nil {
		logx.Error(ctx, "取货码：主码生成失败")
		return "", errorx.New("取货码生成失败", -1)
	}
	// 生成一个子码，并绑定订单
	err = dao.CouponChildCode{}.Create(ctx, dal.Q, []*models.CouponChildCode{
		{
			Code:       code,
			BatchID:    "0",
			OutTradeNo: outTradeNo,
			Status:     int(define.CouponChildCodeStatus_UnUsed),
		},
	})
	if err != nil {
		logx.Error(ctx, "取货码：子码生成失败")
		return "", errorx.New("取货码生成失败", -1)
	}
	return code, nil
}
